﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using HA.ModFlow.Infrastructure;
using System.IO;

using System.Runtime.Serialization;


namespace HA.ModFlow.Domain.DomainLayer
{

    /// <summary>
    /// 用于存储最新的结果数据,为了测试，暂时存储所有的相关数据到内存中，这个只是临时的
    /// </summary>
    [Serializable]
   public class OutputResult
    {

        public OutputResult()
        {
         
            this._cellCenterIHeadDataSet3d = new List<CellCenterDataSet3d>();
 
        }

        
      
        


        //新的结果数据的存储。。。。。。。2011.9.13。。。。。。。。。  

        //[NonSerialized ]
        List<int[,]> _iBound = new List<int[,]>();
        /// <summary>
        /// 存储Modflow生成的 IBound 文件中的 结果数据
        /// </summary>
        public List<int[,]> IBound
        {
            get { return this._iBound; }
            //set { this._iBound = value; }
        }

        List<int[, ,]> _stressPeriodIBound = new List<int[, ,]>();
        /// <summary>
        /// 存储Modflow生成的 IBound 结果数据  list的个数等于应力期ellapseTime数
        /// </summary>
        public List<int[, ,]> StressPeriodIBound
        {
            get { return this._stressPeriodIBound; }
            //set { this._stressPeriodIBound = value; }

        }


           //[NonSerialized]
        List<CellCenterDataSet3d> _cellCenterIHeadDataSet3d;
        /// <summary>
        /// 存放  水头  IHead  数据信息
        /// </summary>
        public List<CellCenterDataSet3d> CellCenterIHeadDataSet3d
        {
            get { return _cellCenterIHeadDataSet3d; }
            //set { _cellCenterDataSet3d = value; }
        }

           //[NonSerialized]
        List<CellCenterDataSet3d> _cellCenterDropDownData;
        /// <summary>
        /// 存放  降深  IDDNUN  数据信息
        /// </summary>
        public List<CellCenterDataSet3d> CellCenterDropDownData
        {
            get { return _cellCenterDropDownData; }
            //set { _cellCenterDropDepthData = value; }
        }

           //[NonSerialized]
        List<BudData> _ccfDataSet;

        public List<BudData> CcfDataSet
        {
            get { return _ccfDataSet; }
            set { _ccfDataSet = value; }
        }


           //[NonSerialized]
        List<MFTimeStepLabel> _mfTimeStepLabel;
        /// <summary>
        /// 存放modflow对应的各应力期中的 ellapseTime 
        /// </summary>
        public List<MFTimeStepLabel> MfTimeStepLabel
        {
            get { return _mfTimeStepLabel; }
            //set { _mfTimeStepLabel = value; }
        }







        #region 公共函数


        public List<List<int[,]>> GetStressStepIBound()
        {

            List<List<int[,]>> result = new List<List<int[,]>>();

            if (_stressPeriodIBound==null )
            {
                return result;
            }

            if (_stressPeriodIBound.Count <=0)
            {
                 return result;
            }

            try
            {
                
                //将MfResult.StressPeriodIBound从形式List<int[, ,]> 转换成形式 List<List<int[,]>> 

                int layerNum = this._stressPeriodIBound[0].GetLength (2);
                int rowNum = this._stressPeriodIBound[0].GetLength(0);
                int colNum = this._stressPeriodIBound[0].GetLength(1);

                for (int numIndex = 0; numIndex < StressPeriodIBound.Count; numIndex++)
                {

                    //从上述存储IBound信息的数据 List<int[, ,]> _stressPeriodIBound中读取对应的IBound数据，而不是使用主程序的
                    List<int[,]> stressIBound = new List<int[,]>();
                    
                    for (int layer = 0; layer < StressPeriodIBound[numIndex].GetLength(2); layer++)
                    {
                        int[,] layerIBound = new int[rowNum, colNum];

                        for (int row = 0; row < this.StressPeriodIBound[numIndex].GetLength(0); row++)
                        {
                            for (int col = 0; col < this.StressPeriodIBound[numIndex].GetLength(1); col++)
                            {

                                layerIBound[row, col] = this.StressPeriodIBound[numIndex][row, col, layer];

                            }

                        }
                        stressIBound.Add(layerIBound);
                    }


                    result.Add(stressIBound);


                }

                return result;

            }
            catch
            {
                result.Clear();

                return result;

            }


        
        }





        /// <summary>
        /// 读取输出文件的数据信息(文件路径，RowsNumber，ColsNumber，LayerNumber，应力期总个数，每个应力期中的时间步数，应力期输出控制)
        /// </summary>
        /// <param name="path">文件绝对路径（不包括文件名及后缀）</param>
        /// <param name="i">主网格 RowsNumber </param>
        /// <param name="j">主网格 ColsNumber </param>
        /// <param name="k">主网格 LayerNumber </param>
        /// <param name="nPeriods">应力期总个数</param>
        /// <param name="stressPeriodNSTP">每个应力期中的时间步数（该List的长度应该等于nPeriods）</param>
        /// <param name="oc">应力期输出控制（输出应力期每个步长，输出应力期最后步长）</param>
       
         //public void LoadData(string path,double invalidValue)//第三次改变需求，每个应力期时间步长的IHead数据和IBound文件中对应的数据一起存储
        public void LoadData(string path, List<int[,]> iBounds, double invalidValue)//第二次重构时，读取二进制文件，将主程序的IBound信息存放进CellCenterDataSet3D中的接口
              //public void LoadData(string path,int i,int j, int k ,int nPeriods,List <int> stressPeriodNSTP , OutputControl oc,List <int [,]> iBounds)//最开始读取txt文件的时候使用的接口
        {


            //水头IHead和降深IDDNUN中的应力期数和各应力期的逝去时间是相同的，在读取水头IHead二进制文件的同时存储应力期逝去时间等信息

            #region 读取水头IHead二进制文件数据

            if (_mfTimeStepLabel == null)
            {
                _mfTimeStepLabel = new List<MFTimeStepLabel>();
            }
            else
            {
                _mfTimeStepLabel.Clear();
            }




            if (this._cellCenterIHeadDataSet3d == null)
            {
                this._cellCenterIHeadDataSet3d = new List<CellCenterDataSet3d>();
            }
            else
            {
                this._cellCenterIHeadDataSet3d.Clear();
            }



            string headFileName = path + "IHEDUN.dat";

            if (System .IO.File .Exists (headFileName ))
            {

                try
                {

                    long partLength = 0;
                    ModflowBinaryFileReader.GetBinaryFilePartLength(headFileName, ref partLength);

                    if (partLength > 0)
                    {

                        #region

                        //取得文件结果，每个BinaryFileData对应一个网格数据
                        List<BinaryFileData> mfBinaryFileData = ModflowBinaryFileReader.ReadModflowBinaryFile(headFileName);

                        if (mfBinaryFileData != null)
                        {


                            if (mfBinaryFileData.Count != _stressPeriodIBound.Count)
                            {
                                //两个Count不相等，应该是出现某种错误，为避免导致抛出异常，提示用户后，使用主程序的Ibound
                                System.Windows.Forms.MessageBox.Show("IBound文件和IHead文件读取的应力期时间步长数据个数不一致，暂时使用主程序设置的IBound！");
                                
                            }




                            for (int numIndex = 0; numIndex < mfBinaryFileData.Count; numIndex++)
                            {
                                MFTimeStepLabel timeStepLabel = null;
                                CellCenterDataSet3d data = null;

                                if (mfBinaryFileData [numIndex ]!=null )
                                {
                                    int layerNum = mfBinaryFileData[numIndex].values.GetLength(2);
                                    int rowNum = mfBinaryFileData[numIndex].values.GetLength(0);
                                    int colNum = mfBinaryFileData[numIndex].values.GetLength(1);

                                    //double[, ,] concValue = new double[rowNum,colNum ,layerNum ];

                                   double[, ,] concValue = mfBinaryFileData[numIndex].values;

                                   if (mfBinaryFileData.Count == _stressPeriodIBound.Count)
                                   {
                                       //从上述存储IBound信息的数据 List<int[, ,]> _stressPeriodIBound中读取对应的IBound数据，而不是使用主程序的
                                       List<int[,]> stressIBound = new List<int[,]>();
                                    

                                       for (int layer = 0; layer < this._stressPeriodIBound[numIndex].GetLength(2); layer++)
                                       {
                                           int  [, ]  layerIBound=new int[rowNum,colNum ];

                                           for (int row = 0; row < this._stressPeriodIBound[numIndex].GetLength(0); row++)
                                           {
                                               for (int col = 0; col < this._stressPeriodIBound[numIndex].GetLength(1); col++)
                                               {

                                                   layerIBound[row,col ]=this._stressPeriodIBound[numIndex][row,col,layer ];

                                               }

                                           }
                                           stressIBound.Add(layerIBound );
                                       }


                                       data = new CellCenterDataSet3d(concValue, stressIBound, invalidValue);

                                   }
                                   else
                                   {
                                       //两个Count不相等，应该是出现某种错误，为避免导致抛出异常，提示用户后，使用主程序的Ibound

                                       //data = new CellCenterDataSet3d(concValue, iBounds);
                                       data = new CellCenterDataSet3d(concValue, iBounds, invalidValue);
                                   }
                                    
                                  




                                    data.Nrows = rowNum;
                                    data.Ncols = colNum;
                                    data.Nlayers = layerNum;
                              
                                    data.Label = mfBinaryFileData[numIndex].KPER.ToString() + "_" + mfBinaryFileData[numIndex].KSTP.ToString();

                                    data.EllapseTime = mfBinaryFileData[numIndex].TotalEllapseTime;


                                    timeStepLabel = new MFTimeStepLabel(data.Label, mfBinaryFileData[numIndex].KPER, mfBinaryFileData[numIndex].KSTP, mfBinaryFileData[numIndex].TotalEllapseTime);
           

                                }

                                this._mfTimeStepLabel.Add(timeStepLabel );
                                this._cellCenterIHeadDataSet3d.Add(data);

                            }// for (int numIndex = 0; numIndex < mfBinaryFileData.Count; numIndex++)

                        }


                        #endregion


                    }


                }
                catch
                {

                    System.Windows.Forms.MessageBox.Show("读取结果文件 IHEDUN.dat 出错了！");

                    _cellCenterIHeadDataSet3d.Clear();


                }


            }
           



            #endregion



            #region 读取降深IDDNUN二进制文件数据



            if (this._cellCenterDropDownData == null)
            {
                this._cellCenterDropDownData = new List<CellCenterDataSet3d>();
            }
            else
            {
                this._cellCenterDropDownData.Clear();
            }

            string dropDepthFileName = path + "IDDNUN.dat";

            if (System.IO.File.Exists(dropDepthFileName))
            {

              

                try
                {

                    long partLength = 0;
                    ModflowBinaryFileReader.GetBinaryFilePartLength(dropDepthFileName, ref partLength);

                    if (partLength > 0)
                    {

                        #region

                        List<BinaryFileData> mfBinaryFileData = ModflowBinaryFileReader.ReadModflowBinaryFile(dropDepthFileName);

                        if (mfBinaryFileData != null)
                        {

                            if (mfBinaryFileData.Count != _stressPeriodIBound.Count)
                            {
                                //两个Count不相等，应该是出现某种错误，为避免导致抛出异常，提示用户后，使用主程序的Ibound
                                System.Windows.Forms.MessageBox.Show("IBound文件和IDDNUN文件读取的应力期时间步长数据个数不一致，暂时使用主程序设置的IBound！");

                            }


                            for (int numIndex = 0; numIndex < mfBinaryFileData.Count; numIndex++)
                            {
                                CellCenterDataSet3d data = null;

                                if (mfBinaryFileData[numIndex] != null)
                                {
                                    int layerNum = mfBinaryFileData[numIndex].values.GetLength(2);
                                    int rowNum = mfBinaryFileData[numIndex].values.GetLength(0);
                                    int colNum = mfBinaryFileData[numIndex].values.GetLength(1);


                                    double[, ,] concValue = mfBinaryFileData[numIndex].values;

                                    //double[, ,] concValue = new double[rowNum, colNum, layerNum];

                                    if (mfBinaryFileData.Count == _stressPeriodIBound.Count)
                                    {
                                        //从上述存储IBound信息的数据 List<int[, ,]> _stressPeriodIBound中读取对应的IBound数据，而不是使用主程序的
                                        List<int[,]> stressIBound = new List<int[,]>();


                                        for (int layer = 0; layer < this._stressPeriodIBound[numIndex].GetLength(2); layer++)
                                        {
                                            int[,] layerIBound = new int[rowNum, colNum];

                                            for (int row = 0; row < this._stressPeriodIBound[numIndex].GetLength(0); row++)
                                            {
                                                for (int col = 0; col < this._stressPeriodIBound[numIndex].GetLength(1); col++)
                                                {

                                                    layerIBound[row, col] = this._stressPeriodIBound[numIndex][row, col, layer];

                                                }

                                            }
                                            stressIBound.Add(layerIBound);
                                        }


                                        //data = new CellCenterDataSet3d(concValue, stressIBound);

                                        data = new CellCenterDataSet3d(concValue, stressIBound,invalidValue );
                                    }
                                    else
                                    {
                                        //两个Count不相等，应该是出现某种错误，为避免导致抛出异常，提示用户后，使用主程序的Ibound
                                        //data = new CellCenterDataSet3d(concValue, iBounds);
                                        data = new CellCenterDataSet3d(concValue, iBounds, invalidValue);

                                    }
                                


                                    data.Nrows = rowNum;
                                    data.Ncols = colNum;
                                    data.Nlayers = layerNum;

                                    data.Label = mfBinaryFileData[numIndex].KPER.ToString() + "_" + mfBinaryFileData[numIndex].KSTP.ToString();

                                    data.EllapseTime = mfBinaryFileData[numIndex].TotalEllapseTime;


                                }

                                this._cellCenterDropDownData.Add(data);

                            }//  for (int numIndex = 0; numIndex < mfBinaryFileData.Count; numIndex++)

                        }

                        #endregion

                    }


                }
                catch
                {

                    System.Windows.Forms.MessageBox.Show("读取结果文件 IDDNUN.dat 出错了！");

                    _cellCenterDropDownData.Clear();

              

                }


            }
           


            #endregion


            //HeadFileDataSetReader headFileReader = new HeadFileDataSetReader(path, i, j, k, nPeriods, stressPeriodNSTP, oc, iBounds);

            //List<DataSet> _dataSet = headFileReader.ReadData();

            //if (this._cellCenterDataSet3d == null)
            //{
            //    this._cellCenterDataSet3d = new List<CellCenterDataSet3d>();
            //}

            //this._cellCenterDataSet3d.Clear();

            //for (int index = 0; index < _dataSet.Count; index++)
            //{
            //    this._cellCenterDataSet3d.Add((CellCenterDataSet3d)_dataSet[index]);
            //}


            //this._cellCenterDataSet3d = headFileReader.ReadData();



        }





        
        /// <summary>
        /// 读取 边界txt文件 IBound 的结果 并将数据反向更新到主程序中的IBound中
       /// </summary>
       /// <param name="path">文件路径（不包括文件名和后缀）</param>
       /// <param name="i">主网格 RowsNumber</param>
       /// <param name="j">主网格 ColsNumber</param>
       /// <param name="k"> 主网格 LayerNumber</param>
       /// <param name="nPeriods">应力期总个数</param>
       /// <param name="stressPeriodNSTP">各应力期的时间步数</param>
       /// <param name="oc">应力期输出类型</param>
        public void LoadIBoundData(string path, int i, int j, int k, int nPeriods, List<int> stressPeriodNSTP, OutputControl oc, GridData gridData)
        {

            // 读取边界文件 IBound txt数据
            List<int[, ,]> result = new List<int[, ,]>();


            try
            {
                //读取IBound结果文件，存放到临时变量 result 中
                result = IBoundTxtFileReader.ReadIBoundTxtFile(path, i, j, k, nPeriods, stressPeriodNSTP, oc);


                //对结果进行处理
                if (result != null && result.Count > 0 && result[0] != null)
                {
                    this._stressPeriodIBound.Clear();

                    //将读取的结果数据保存到 StressPeriodIBound 中以供外围访问。
                    for (int index = 0; index < result.Count; index++)
                    {
                        this.StressPeriodIBound.Add((int[, ,])result[index].Clone());
                    }


                    //if (this.StressPeriodIBound.Count > 0 && this.StressPeriodIBound[0] != null)
                    //{
                    //    //反向更新主程序数据

                    //    #region
                    //    if (gridData != null && gridData.WaterGrid != null)
                    //    {
                    //        //先按照返回最后一个应力期的IBound的数据信息处理

                    //        int lastIndex = this._stressPeriodIBound.Count - 1;//最后一个应力期的数据在List中的索引值

                    //        List<int[,]> lastPeriodIBound = new List<int[,]>();//IBound信息

                    //        int[, ,] tempLastPeriod = (int[, ,])this._stressPeriodIBound[lastIndex].Clone();//存放顺序为 Row，Col，Layer（i，j，k）

                    //        int rowNum = tempLastPeriod.GetLength(0);
                    //        int colNum = tempLastPeriod.GetLength(1);


                    //        for (int layer = 0; layer < tempLastPeriod.GetLength(2); layer++)
                    //        {
                    //            int[,] layerIBound = new int[rowNum, colNum];

                    //            for (int row = 0; row < rowNum; row++)
                    //            {
                    //                for (int col = 0; col < colNum; col++)
                    //                {

                    //                    layerIBound[row, col] = tempLastPeriod[row, col, layer];

                    //                }
                    //            }

                    //            lastPeriodIBound.Add(layerIBound);
                    //        }

                    //        if ((lastPeriodIBound.Count > 0) && (lastPeriodIBound.Count == tempLastPeriod.GetLength(2)))//确保取得数据的过程没有出现明显的错误
                    //        {
                    //            //更新数据并触发事件
                    //            //gridData.WaterGrid.SetIBounds(lastPeriodIBound);

                    //        }

                    //    }
                    //    #endregion

                    //}

                }

            }
            catch
            {
                System.Windows.Forms.MessageBox.Show("读取Modflow的 IBOUUN.dat 结果文件时出错！");

                return;
            }
        }


        #endregion



        #region 反序体制

        [OnDeserialized]
        public void OnDeserialized(StreamingContext context)
        {

            if (this._iBound ==null )
            {
                this._iBound = new List<int[,]>();
            }

            if (this._stressPeriodIBound ==null )
            {
                this._stressPeriodIBound = new List<int[, ,]>();
            }

            if (this.CellCenterIHeadDataSet3d==null )
            {
                this._cellCenterIHeadDataSet3d = new List<CellCenterDataSet3d>();
            }

            if (this._cellCenterDropDownData == null)
            {
                this._cellCenterDropDownData = new List<CellCenterDataSet3d>();
            }

            if (this._ccfDataSet == null)
            {
                this._ccfDataSet = new List<BudData>();
            }
            if (this._mfTimeStepLabel == null)
            {
                this._mfTimeStepLabel = new List<MFTimeStepLabel>();
            }


        }

        [OnSerializing]
        public void OnSerializing(StreamingContext context)
        {




        }

        #endregion









    }

}
